package icu.groot.alan.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import icu.groot.alan.entity.TokenEntity;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Map;

public class Token {
    /**
     * 签名
     */
    private static final String SIGN = "alan@groot.com";

    /**
     * generateToken 生成token: header.payload.sign
     *
     * @return String token
     */
    public static String generateToken(Map<String, String> payload){
        //日历类
        Calendar instance = Calendar.getInstance();
        //20分钟过期
        instance.add(Calendar.MINUTE, 20);
        JWTCreator.Builder builder = JWT.create();
        //payload
        for (Map.Entry<String, String> entry : payload.entrySet()) {
            String name = entry.getKey();
            String value = entry.getValue();
            builder.withClaim(name, value);
        }
        String token = null;
        //指定令牌过期时间
        try {
            token = builder.withExpiresAt(instance.getTime())
                    //签名
                    .sign(Algorithm.HMAC256(SIGN));
        } catch (UnsupportedEncodingException e) {
            System.out.println(e.getMessage());
        }
        return token;
    }

    /**
     * 验证token合法性
     *
     * @param token token
     */
    public static TokenEntity verify(String token){
        DecodedJWT decodedJWT = null;
        TokenEntity tokenEntity = new TokenEntity();
        try {
            decodedJWT = JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
            Map<String, Claim> claims = decodedJWT.getClaims();
            Class<? extends TokenEntity> aClass = tokenEntity.getClass();
            for (Map.Entry<String, Claim> entry : claims.entrySet()) {
                aClass.getDeclaredField(entry.getKey());
                Field field = aClass.getDeclaredField(entry.getKey());
                String methodName = "set"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);
                Method method = aClass.getDeclaredMethod(methodName, String.class);
                method.invoke(tokenEntity,entry.getValue().as(String.class));
            }
        }catch (Exception e){
            System.out.println(e.getMessage());
            return null;
        }
        return tokenEntity;
    }
}
